
package com.rt.schedulenew.utils.coder;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public abstract class RSACoder extends SecurityCoder
{
    public static final String KEY_ALGORITHM = "RSA";
    public static final String KEY_CIPHER = "RSA/ECB/PKCS1Padding";
    public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";
    private static final int KEY_SIZE = 512;
    
    public static byte[] sign(final byte[] data, final byte[] privateKey) throws Exception {
        final PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
        final Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(priKey);
        signature.update(data);
        return signature.sign();
    }
    
    public static boolean verify(final byte[] data, final byte[] publicKey, final byte[] sign) throws Exception {
        final X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PublicKey pubKey = keyFactory.generatePublic(keySpec);
        final Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initVerify(pubKey);
        signature.update(data);
        return signature.verify(sign);
    }
    
    public static byte[] decryptByPrivateKey(final byte[] data, final byte[] key) throws Exception {
        final PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(2, privateKey);
        return cipher.doFinal(data);
    }
    
    public static byte[] decryptByPublicKey(final byte[] data, final byte[] key) throws Exception {
        final X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(2, publicKey);
        return cipher.doFinal(data);
    }
    
    public static byte[] encryptByPublicKey(final byte[] data, final byte[] key) throws Exception {
        final X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(1, publicKey);
        return cipher.doFinal(data);
    }
    
    public static byte[] encryptByPrivateKey(final byte[] data, final byte[] key) throws Exception {
        final PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(1, privateKey);
        return cipher.doFinal(data);
    }
    
    public static byte[] getPrivateKey(final Map<String, Object> keyMap) throws Exception {
        final Key key = (Key) keyMap.get("RSAPrivateKey");
        return key.getEncoded();
    }
    
    public static byte[] getPublicKey(final Map<String, Object> keyMap) throws Exception {
        final Key key =(Key) keyMap.get("RSAPublicKey");
        return key.getEncoded();
    }
    
    public static Map<String, Object> initKey() throws Exception {
        final KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(512);
        final KeyPair keyPair = keyPairGen.generateKeyPair();
        final RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
        final RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
        final Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put("RSAPublicKey", publicKey);
        keyMap.put("RSAPrivateKey", privateKey);
        return keyMap;
    }
    
    public static Map<String, Object> initKey(final int size) throws Exception {
        final KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(size);
        final KeyPair keyPair = keyPairGen.generateKeyPair();
        final RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
        final RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
        final Map<String, Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put("RSAPublicKey", publicKey);
        keyMap.put("RSAPrivateKey", privateKey);
        return keyMap;
    }
}
